{ name: 'GetExtensionErrors',
inSignature: 's',
outSignature: 'as'
+ },
+ { name: 'ScreenshotArea',
+ inSignature: 'iiiis',
+ outSignature: 'b'
+ },
+ { name: 'ScreenshotWindow',
+ inSignature: 'bs',
+ outSignature: 'b'
+ },
+ { name: 'Screenshot',
+ inSignature: 's',
+ outSignature: 'b'
}
],
signals: [],
return [success, returnValue];
},
+ /**
+ * ScreenshotArea:
+ * @x: The X coordinate of the area
+ * @y: The Y coordinate of the area
+ * @width: The width of the area
+ * @height: The height of the area
+ * @filename: The filename for the screenshot
+ *
+ * Takes a screenshot of the passed in area and saves it
+ * in @filename as png image, it returns a boolean
+ * indicating whether the operation was successful or not.
+ *
+ */
+ ScreenshotAreaAsync : function (x, y, width, height, filename, callback) {
+ global.screenshot_area (x, y, width, height, filename, function (obj, result) { callback(result); });
+ },
+
+ /**
+ * ScreenshotWindow:
+ * @include_frame: Whether to include the frame or not
+ * @filename: The filename for the screenshot
+ *
+ * Takes a screenshot of the focused window (optionally omitting the frame)
+ * and saves it in @filename as png image, it returns a boolean
+ * indicating whether the operation was successful or not.
+ *
+ */
+ ScreenshotWindow : function (include_frame, filename) {
+ return global.screenshot_window (include_frame, filename);
+ },
+
+ /**
+ * Screenshot:
+ * @filename: The filename for the screenshot
+ *
+ * Takes a screenshot of the whole screen and saves it
+ * in @filename as png image, it returns a boolean
+ * indicating whether the operation was successful or not.
+ *
+ */
+ ScreenshotAsync : function (filename, callback) {
+ global.screenshot(filename, function (obj, result) { callback(result); });
+ },
+
ListExtensions: function() {
return ExtensionSystem.extensionMeta;
},
g_free (calendar_server_exe);
}
+
+static void
+grab_screenshot (ClutterActor *stage,
+ _screenshot_data *screenshot_data)
+{
+ MetaScreen *screen = shell_global_get_screen (screenshot_data->global);
+ cairo_status_t status;
+ cairo_surface_t *image;
+ guchar *data;
+ int width, height;
+
+ meta_plugin_query_screen_size (screenshot_data->global->plugin, &width, &height);
+ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ data = cairo_image_surface_get_data (image);
+
+ cogl_flush();
+
+ cogl_read_pixels (0, 0, width, height, COGL_READ_PIXELS_COLOR_BUFFER, CLUTTER_CAIRO_FORMAT_ARGB32, data);
+
+ cairo_surface_mark_dirty (image);
+
+ if (meta_screen_get_n_monitors (screen) > 1)
+ {
+ cairo_region_t *screen_region = cairo_region_create ();
+ cairo_region_t *stage_region;
+ MetaRectangle monitor_rect;
+ cairo_rectangle_int_t stage_rect;
+ int i;
+ cairo_t *cr;
+
+ for (i = meta_screen_get_n_monitors (screen) - 1; i >= 0; i--)
+ {
+ meta_screen_get_monitor_geometry (screen, i, &monitor_rect);
+ cairo_region_union_rectangle (screen_region, (const cairo_rectangle_int_t *) &monitor_rect);
+ }
+
+ stage_rect.x = 0;
+ stage_rect.y = 0;
+ stage_rect.width = width;
+ stage_rect.height = height;
+
+ stage_region = cairo_region_create_rectangle ((const cairo_rectangle_int_t *) &stage_rect);
+ cairo_region_xor (stage_region, screen_region);
+ cairo_region_destroy (screen_region);
+
+ cr = cairo_create (image);
+
+ for (i = 0; i < cairo_region_num_rectangles (stage_region); i++)
+ {
+ cairo_rectangle_int_t rect;
+ cairo_region_get_rectangle (stage_region, i, &rect);
+ cairo_rectangle (cr, (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
+ cairo_fill (cr);
+ }
+
+ cairo_destroy (cr);
+ cairo_region_destroy (stage_region);
+ }
+
+
+ status = cairo_surface_write_to_png (image, screenshot_data->filename);
+ cairo_surface_destroy (image);
+
+ if (screenshot_data->callback)
+ screenshot_data->callback (screenshot_data->global, status == CAIRO_STATUS_SUCCESS);
+
+ g_signal_handlers_disconnect_by_func (stage, (void *)grab_screenshot, (gpointer)screenshot_data);
+ g_free (screenshot_data->filename);
+ g_free (screenshot_data);
+}
+
+static void
+grab_area_screenshot (ClutterActor *stage,
+ _screenshot_data *screenshot_data)
+{
+ cairo_status_t status;
+ cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, screenshot_data->width, screenshot_data->height);
+ guchar *data = cairo_image_surface_get_data (image);
+
+ cogl_flush();
+
+ cogl_read_pixels (screenshot_data->x, screenshot_data->y, screenshot_data->width, screenshot_data->height,
+ COGL_READ_PIXELS_COLOR_BUFFER, CLUTTER_CAIRO_FORMAT_ARGB32, data);
+
+ cairo_surface_mark_dirty (image);
+ status = cairo_surface_write_to_png (image, screenshot_data->filename);
+ cairo_surface_destroy (image);
+
+ if (screenshot_data->callback)
+ screenshot_data->callback (screenshot_data->global, status == CAIRO_STATUS_SUCCESS);
+
+ g_signal_handlers_disconnect_by_func (stage, (void *)grab_area_screenshot, (gpointer)screenshot_data);
+ g_free (screenshot_data->filename);
+ g_free (screenshot_data);
+}
+
+/**
+ * shell_global_screenshot:
+ * @global: the #ShellGlobal
+ * @filename: The filename for the screenshot
+ * @callback: (scope async): function to call returning success or failure
+ * of the async grabbing
+ *
+ * Takes a screenshot of the whole screen
+ * in @filename as png image.
+ *
+ */
+void
+shell_global_screenshot (ShellGlobal *global,
+ const char *filename,
+ ShellGlobalScreenshotCallback callback)
+{
+ ClutterActor *stage;
+ _screenshot_data *data = g_new0 (_screenshot_data, 1);
+
+ data->global = global;
+ data->filename = g_strdup (filename);
+ data->callback = callback;
+
+ stage = CLUTTER_ACTOR (meta_plugin_get_stage (global->plugin));
+
+ g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), (gpointer)data);
+
+ clutter_actor_queue_redraw (stage);
+}
+
+/**
+ * shell_global_screenshot_area:
+ * @global: the #ShellGlobal
+ * @x: The X coordinate of the area
+ * @y: The Y coordinate of the area
+ * @width: The width of the area
+ * @height: The height of the area
+ * @filename: The filename for the screenshot
+ * @callback: (scope async): function to call returning success or failure
+ * of the async grabbing
+ *
+ * Takes a screenshot of the passed in area and saves it
+ * in @filename as png image.
+ *
+ */
+void
+shell_global_screenshot_area (ShellGlobal *global,
+ int x,
+ int y,
+ int width,
+ int height,
+ const char *filename,
+ ShellGlobalScreenshotCallback callback)
+{
+ ClutterActor *stage;
+ _screenshot_data *data = g_new0 (_screenshot_data, 1);
+
+ data->global = global;
+ data->filename = g_strdup (filename);
+ data->x = x;
+ data->y = y;
+ data->width = width;
+ data->height = height;
+ data->callback = callback;
+
+ stage = CLUTTER_ACTOR (meta_plugin_get_stage (global->plugin));
+
+ g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), (gpointer)data);
+
+ clutter_actor_queue_redraw (stage);
+}
+
+/**
+ * shell_global_screenshot_window:
+ * @global: the #ShellGlobal
+ * @include_frame: Whether to include the frame or not
+ *
+ * @filename: The filename for the screenshot
+ *
+ * Takes a screenshot of the focused window (optionally omitting the frame)
+ * in @filename as png image.
+ *
+ * Return value: success or failure.
+ */
+gboolean
+shell_global_screenshot_window (ShellGlobal *global,
+ gboolean include_frame,
+ const char *filename)
+{
+ CoglHandle texture;
+ cairo_surface_t *image;
+ guchar *data;
+
+ MetaScreen *screen = meta_plugin_get_screen (global->plugin);
+ MetaDisplay *display = meta_screen_get_display (screen);
+ MetaWindow *window = meta_display_get_focus_window (display);
+ ClutterActor *window_actor;
+
+ cairo_status_t status;
+
+ window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
+ texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (meta_window_actor_get_texture (META_WINDOW_ACTOR (window_actor))));
+
+ if (!include_frame)
+ {
+ MetaRectangle *window_rect = meta_window_get_rect (window);
+ texture = cogl_texture_new_from_sub_texture (texture,
+ window_rect->x,
+ window_rect->y,
+ window_rect->width,
+ window_rect->height);
+
+ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ window_rect->width,
+ window_rect->height);
+ }
+ else
+ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ clutter_actor_get_width (window_actor),
+ clutter_actor_get_height (window_actor));
+
+ data = cairo_image_surface_get_data (image);
+
+ cogl_flush();
+
+ cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32, 0, data);
+
+ cairo_surface_mark_dirty (image);
+ status = cairo_surface_write_to_png (image, filename);
+ cairo_surface_destroy (image);
+
+ return status == CAIRO_STATUS_SUCCESS;
+}